﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using web_api.Data;
using web_api.DtoParameters;
using web_api.Entities;
using web_api.Helpers;

namespace web_api.Services
{
  public class CompanyRepository : ICompanyRepository
  {
    private readonly RoutineDbContext _context;
    public CompanyRepository(RoutineDbContext context)
    {
      _context = context ?? throw new ArgumentNullException(nameof(context));
    }
    public async Task<PagedList<Company>> GetCompaniesAsync(CompanyDtoParameters parameters)
    {
      //if (parameters == null)
      //{
      //  throw new ArgumentNullException(nameof(parameters));
      //}
     /* if (string.IsNullOrWhiteSpace(parameters.CompanyName) &&
        string.IsNullOrWhiteSpace(parameters.SearchTerm))
      {
        return await _context.Companies.ToListAsync();
      }*/
      var queryExpreesion = _context.Companies as IQueryable<Company>;
      if (!string.IsNullOrWhiteSpace(parameters.CompanyName))
      {
        parameters.CompanyName = parameters.CompanyName.Trim();
        queryExpreesion = queryExpreesion.Where(x => x.Name == parameters.CompanyName);
      }
      if (!string.IsNullOrWhiteSpace(parameters.SearchTerm))
      {
        parameters.SearchTerm = parameters.SearchTerm.Trim();
        queryExpreesion = queryExpreesion.Where(x => x.Name.Contains(parameters.SearchTerm)
          || x.Introduction.Contains(parameters.SearchTerm));
      }
      //queryExpreesion = queryExpreesion.Skip(parameters.PageSize * (parameters.PageNumber - 1)).Take(parameters.PageSize);

      return await PagedList<Company>.CreateAsync(queryExpreesion, parameters.PageNumber, parameters.PageSize);
    }
    public async Task<Company> GetCompanyAsync(Guid companyId)
    {
      if (companyId == Guid.Empty)
      {
        throw new ArgumentNullException(nameof(companyId));
      }
      return await _context.Companies.FirstOrDefaultAsync(x => x.Id == companyId);
    }
    public async Task<IEnumerable<Company>> GetCompaniesAsync(IEnumerable<Guid> companyIds)
    {
      if (companyIds == null)
      {
        throw new ArgumentNullException(nameof(companyIds));
      }
      return await _context.Companies.Where(x => companyIds.Contains(x.Id))
        .OrderBy(x => x.Name).ToListAsync();
    }
    public void AddCompany(Company company)
    {
      if (company == null)
      {
        throw new ArgumentNullException(nameof(company));
      }
      company.Id = Guid.NewGuid();
      if (company.Employees != null)
      {
        foreach (var employee in company.Employees)
        {
          employee.Id = Guid.NewGuid();
        }
      }
      _context.Companies.Add(company);
    }
    public void UpdateCompany(Company company)
    {
      //_context.Entry(company).State = EntityState.Modified;
    }
    public void DeleteCompany(Company company)
    {
      if (company == null)
      {
        throw new ArgumentNullException(nameof(company));
      }
      _context.Companies.Remove(company);
    }
    public async Task<bool> CompanyExistsAsync(Guid companyId)
    {
      if (companyId == Guid.Empty)
      {
        throw new ArgumentNullException(nameof(companyId));
      }
      return await _context.Companies.AnyAsync(x => x.Id == companyId);
    }
    public async Task<IEnumerable<Employee>> GetEmployeesAsync(Guid companyId, EmployeeDtoParameters parameters)
    {
      if (companyId == Guid.Empty)
      {
        throw new ArgumentNullException(nameof(companyId));
      }
      if (string.IsNullOrEmpty(parameters.Gender) && string.IsNullOrEmpty(parameters.Q))
      {
        return await _context.Employees.Where(x => x.CompanyId == companyId).
          OrderBy(x => x.EmployeeNo).ToListAsync();
      }
      var items = _context.Employees.Where(x => x.CompanyId == companyId);
      if (!string.IsNullOrWhiteSpace(parameters.Gender))
      {
        var genderStr = parameters.Gender.Trim();
        var gender = Enum.Parse<Gender>(genderStr);
        items = items.Where(x => x.Gender == gender);
      }
      if (!string.IsNullOrWhiteSpace(parameters.Q))
      {
        parameters.Q = parameters.Q.Trim();
        items = items.Where(x => x.EmployeeNo.Contains(parameters.Q) || x.FirstName.Contains(parameters.Q) || x.LastName.Contains(parameters.Q));
      }
      if (!string.IsNullOrWhiteSpace(parameters.OrderBy)) {
        if (parameters.OrderBy.ToLowerInvariant() == "name") {
          items = items.OrderBy(x => x.FirstName).ThenBy(x => x.LastName);
        }
      }
      return await items.OrderBy(x => x.EmployeeNo).ToListAsync();

    }
    public async Task<Employee> GetEmployeeAsync(Guid companyId, Guid employeeId)
    {
      if (companyId == Guid.Empty)
      {
        throw new ArgumentNullException(nameof(companyId));
      }
      if (employeeId == Guid.Empty)
      {
        throw new ArgumentNullException(nameof(employeeId));
      }
      return await _context.Employees.Where(x => x.CompanyId == companyId && x.Id == employeeId).
        FirstOrDefaultAsync();
    }
    public void AddEmployee(Guid companyId, Employee employee)
    {
      if (companyId == Guid.Empty)
      {
        throw new ArgumentNullException(nameof(companyId));
      }
      if (employee == null)
      {
        throw new ArgumentNullException(nameof(employee));
      }
      employee.CompanyId = companyId;
      _context.Employees.Add(employee);
    }
    public void UpdateEmployee(Employee employee)
    {
      //_context.Entry(employee).State = EntityState.Modified;
    }
    public void DeleteEmployee(Employee employee)
    {
      _context.Employees.Remove(employee);
    }
    public async Task<bool> SaveAsync()
    {
      return await _context.SaveChangesAsync() >= 0;
    }




  }
}
